package net.lovesrc.support.service.generator.idcard;

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 生成器
 *
 * @author gelic
 * Created in 20:33 2018/10/29
 * @since
 */
public class IDCardGeneratorUtil {

    private static final int[] CHECK_PARAMS = new int[]{7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
    private static final String[] CHECK_LEAVE = new String[]{"1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"};
    private static final List<String> special_provinces = Arrays.asList(new String[]{"北京,天津,上海,重庆"});
    private static final List<String> special_citys = Arrays.asList(new String[]{"直辖县级"});
    /**
     * key：城市id      value：城市名称
     */
    private static final Map<String, String> ID_CITYNAME_MAP = new HashMap<>();
    /**
     * key：城市id   value：父级城市id
     */
    private static final Map<String, String> ID_PID_MAP = new HashMap<>();
    /**
     * 级别为3的城市id
     */
    private static final List<String> DISTRICT_IDS = new ArrayList<>();
    /**
     * key：城市id   value：城市详细详细 例如  ：黑龙江省鸡西市鸡东县
     */
    private static final Map<String, String> ID_CITY_FULL_MAP = new HashMap<>();

    private static final List<String> female_names = new ArrayList<>();
    private static final List<String> male_names = new ArrayList<>();

    private static final Random DEFALUT_RAND = new Random(System.currentTimeMillis());

    static {
        try {
            initCity();
            initName();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    //初始化姓名
    private static void initName() throws IOException {
        {
            InputStream is = IDCardGeneratorUtil.class.getResourceAsStream("/china_female_name.txt");
            Stream<String> lines = new BufferedReader(new InputStreamReader(is, "utf-8")).lines();
            List<String> names = lines.filter(str -> !StringUtils.isBlank(str)).collect(Collectors.toList());
            female_names.addAll(names);
        }

        {
            InputStream is = IDCardGeneratorUtil.class.getResourceAsStream("/china_male_name.txt");
            Stream<String> lines = new BufferedReader(new InputStreamReader(is, "utf-8")).lines();
            List<String> names = lines.filter(str -> !StringUtils.isBlank(str)).collect(Collectors.toList());
            male_names.addAll(names);
        }

        if (female_names.isEmpty() || male_names.isEmpty()) {
            throw new RuntimeException("初始化姓名失败");
        }
        System.out.println("加载了" + female_names.size() + male_names.size() + "条城市信息");
    }

    //初始化城市
    private static void initCity() throws IOException {
        InputStream is = IDCardGeneratorUtil.class.getResourceAsStream("/city.csv");
        Stream<String> lines = new BufferedReader(new InputStreamReader(is, "utf-8")).lines();
        List<JSONObject> allChinaInnerCitys = lines.filter(line -> !StringUtils.isEmpty(line))
                .map(line -> {
                    String[] arr = line.split(",");
                    if (arr.length != 10) {
                        return null;
                    } else {
                        //滤掉港澳台
                        String idStr = arr[0];
                        if (Long.valueOf(idStr) >= 710000) {
                            return null;
                        }
                        return new JSONObject()
                                .fluentPut("ID", arr[0])
                                .fluentPut("Name", arr[1])
                                .fluentPut("ParentId", arr[2])
                                .fluentPut("LevelType", arr[4]);
                    }
                })
                .filter(jsonObject -> jsonObject != null)
                .collect(Collectors.toList());

        allChinaInnerCitys.stream()
                .forEach(jsonObject -> {
                            String id = jsonObject.getString("ID");
                            String name = jsonObject.getString("Name");
                            String pid = jsonObject.getString("ParentId");
                            ID_CITYNAME_MAP.put(id, name);
                            ID_PID_MAP.put(id, pid);
                            String levelType = jsonObject.getString("LevelType");
                            if ("3".equals(levelType)) {
                                DISTRICT_IDS.add(id);
                            }
                        }
                );
        DISTRICT_IDS.stream().forEach(districtId -> {
            String districtName = ID_CITYNAME_MAP.get(districtId);
            String cityId = ID_PID_MAP.get(districtId);

            String cityName = ID_CITYNAME_MAP.get(cityId);
            String provinceId = ID_PID_MAP.get(cityId);

            String provinceName = ID_CITYNAME_MAP.get(provinceId);
            String countryId = ID_PID_MAP.get(provinceId);
            //合法地址
            if ("100000".equals(countryId)) {
                StringBuilder addrNameSB = new StringBuilder();
                if (!special_provinces.contains(provinceName)) {
                    addrNameSB.append(provinceName);
                }
                if (!special_citys.contains(cityName)) {
                    addrNameSB.append(cityName);
                }
                addrNameSB.append(districtName);
                ID_CITY_FULL_MAP.put(districtId, addrNameSB.toString());
            }
        });

        if (DISTRICT_IDS.isEmpty() || ID_CITY_FULL_MAP.isEmpty()) {
            throw new RuntimeException("初始化城市失败");
        }
        System.out.println("加载了" + DISTRICT_IDS.size() + "条城市信息");
    }

    /**
     * 生成身份证校验码
     *
     * @author clg
     * Created at 14:17 2018/12/4
     * @since 1.1
     */
    static String getIDCardCheckNum(String preNo) {
        if (preNo.length() != 17) {
            throw new RuntimeException("无效的身份证前缀");
        }
        int checkCode = 0;
        for (int i = 0; i < preNo.length(); i++) {
            char c = preNo.charAt(i);
            checkCode += Integer.parseInt(String.valueOf(c)) * CHECK_PARAMS[i];
        }
        return CHECK_LEAVE[checkCode % 11];
    }

    static String generateBirthday(Random random) {
        return generateBirthday(random, 18, 60);
    }

    static String generateBirthday(Random random, int startAge, int endAge) {
        random = random == null ? DEFALUT_RAND : random;
        int beforeDays = random.nextInt((endAge - startAge) * 365 + (endAge - startAge) / 4);
        beforeDays = beforeDays + startAge * 365 + startAge / 4;
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_YEAR, -beforeDays);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("YYYYMMdd");
        return simpleDateFormat.format(calendar.getTime());
    }

    static String generateOrderCode(Random random, Boolean male) {
        random = random == null ? DEFALUT_RAND : random;
        if (male == null) {
            male = random.nextInt(2) == 0;
        }
        int code = random.nextInt(1000);
        //ordercode 男是奇数,女是偶数
        if (male) {
            code = code % 2 == 0 ? code + 1 : code;
        } else {
            code = code % 2 == 1 ? code - 1 : code;
        }
        return StringUtils.leftPad(code + "", 3, "0");
    }


    static String getName(Random random, Boolean male) {
        random = random == null ? DEFALUT_RAND : random;
        if (male == null) {
            male = random.nextInt(2) == 0;
        }

        if (male) {
            int index = random.nextInt(male_names.size());
            return male_names.get(index);
        } else {
            int index = random.nextInt(female_names.size());
            return female_names.get(index);
        }
    }

    static String getDistrictId(Random random) {
        int i = random.nextInt(IDCardGeneratorUtil.DISTRICT_IDS.size());
        return IDCardGeneratorUtil.DISTRICT_IDS.get(i);
    }

    static String getAddr(String districtId) {
        return IDCardGeneratorUtil.ID_CITY_FULL_MAP.get(districtId);
    }

    static boolean getGender(Random random) {
        random = random == null ? DEFALUT_RAND : random;
        return random.nextInt(2) == 0;
    }
}
